package com.example.wordbook;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.SearchView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;


public class WordsFragment extends Fragment {
    private WordViewModel wordViewModel;
    private RecyclerView recyclerView;
    private MyAdapter myAdapter1, myAdapter2;
    private FloatingActionButton floatingActionButton;//定义变量
    private LiveData<List<Word>> filteredWords;//过滤后的词汇
    private static final String IS_USING_CARD_VIEW = "is_using_card_view";
    private List<Word> allWords;
    private boolean undoAction;
    private DividerItemDecoration dividerItemDecoration;
    public WordsFragment() {
        setHasOptionsMenu(true);
        // 必需的空公共构造函数，它在创建类对象时会自动被调用，用于构造类对象。由于Fragment中默认不显示菜单，所以需要在构造方法中设置显示菜单
    }

    //搜索功能
    //制作fragment中的搜索栏的监听器，在onActivityCreated中通过getActivity()获取到Fragment关联的Activity，在onActivityCreated中为按钮添加监听事件。
    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.main_enu, menu);
        //设置搜索栏点击时，系统名不被隐藏的方法：
        SearchView searchView = (SearchView) menu.findItem(R.id.app_bar_search).getActionView();
        searchView.setMaxWidth(750);//设置搜索栏宽度以防系统名被隐藏
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {//监听里面内容改变的监听器
            @Override
            public boolean onQueryTextSubmit(String query) {//确定提交相关
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {//内容改变
                //制作模糊匹配查询
                String patten = newText.trim();
                //避免两次观察的碰撞，先移除之前的观察，否则第二次搜的关键词列表会显示前一个你查询过的单词
                filteredWords.removeObservers(requireActivity()); //不写这句会报错（试了好多次都不行，最后网上查的方法
                //根据筛选条件获取新的模糊查询添加观察
                filteredWords = wordViewModel.findWordsWithPattern(patten);
                //因LiveData造成的添加数据后的搜索观察（observer）失误
                 // 对于filteredWords.observe观察
                 //fragment在观察过程中依赖requireActivity
                 //由于Activity不曾被摧毁，
                 //所以将Activity作为观察的owner
                 //会出现界面上的一个重叠
                 //需要解决将getActivity()修改采用getViewLifecycleOwner()
                filteredWords.observe(getViewLifecycleOwner(), new Observer<List<Word>>() {
                    @Override
                    public void onChanged(List<Word> words) {//onChanged()内部方法
                        int temp = myAdapter1.getItemCount();
                        allWords = words;
                        if (temp != words.size()) {
                            myAdapter1.submitList(words);
                            myAdapter2.submitList(words);
                        }
                    }
                });
                return true; //如果事件处理结束，则返回true
            }
        });


    }
    //制作清空数据功能和切换布局功能
    //在WordsFragment中设置了菜单功能，点击清空数据会弹出alertDialog对话框，若选择确认，则调用wordViewModel中的deleteAll（）方法删除所有数据；
    // 点击切换视图时，会先在SharePreferences中获得现在时什么视图的值，然后调用recyclerView的方法设置另一个视图。
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        //菜单栏的可选项点击事件的实现（本次为清空数据）,需要在构造方法中设置显示菜单
        switch (item.getItemId()) {
            case R.id.clearData: //选中清空数据时弹出确认对话框
                AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
                builder.setTitle("清空数据");
                builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        wordViewModel.deleteAllWords();//确定时才从ViewModel中清空数据
                    }
                });
                builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //取消时不做处理即可
                    }
                });
                builder.create();
                builder.show();
                break;
            case R.id.switchViewType: //选中切换视图时
                //创建用户偏好设置SharedPreferences保存切换的视图（不设置会在切换视图做添加数据操作的时候回归普通视图）
                SharedPreferences sp = requireActivity().getSharedPreferences("view_type_sp", Context.MODE_PRIVATE);
                boolean viewType = sp.getBoolean(IS_USING_CARD_VIEW, false);
                SharedPreferences.Editor editor = sp.edit();
                if (viewType) {
                    //当前使用的时卡片布局
                    recyclerView.setAdapter(myAdapter1);//改变为普通布局
                    recyclerView.addItemDecoration(dividerItemDecoration);
                    editor.putBoolean(IS_USING_CARD_VIEW, false);//将用户偏好设置改变为false
                } else {
                    recyclerView.setAdapter(myAdapter2);
                    recyclerView.removeItemDecoration(dividerItemDecoration);
                    editor.putBoolean(IS_USING_CARD_VIEW, true);
                }
                editor.apply();//用户偏好设置存储

        }
        return super.onOptionsItemSelected(item);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_words, container, false);//（view，flag）
    }
//在填充数据后通过用户偏好设置sharedPreferences保持原本界面布局（包括填充数据提交和重新进入界面）
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        wordViewModel = new ViewModelProvider(this, new SavedStateViewModelFactory(requireActivity().getApplication(),this)).get(WordViewModel.class);
        recyclerView = requireActivity().findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(requireActivity()));
        myAdapter1 = new MyAdapter(false, wordViewModel);//不使用卡片
        myAdapter2 = new MyAdapter(true, wordViewModel);//使用卡片

        //修正视图序号上的改变（变更为数据层面的序号改变）
        //设置recyclerView的回调
        recyclerView.setItemAnimator(new DefaultItemAnimator() {
            //复写回调中的函数onAnimationFinished
            @Override
            public void onAnimationFinished(@NonNull RecyclerView.ViewHolder viewHolder) {
                super.onAnimationFinished(viewHolder);
                LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                //判空
                if (linearLayoutManager != null) {
                    int firstPosition = linearLayoutManager.findFirstVisibleItemPosition();
                    int lastPosition = linearLayoutManager.findLastVisibleItemPosition();
                    //做序号的循环
                    for (int i = firstPosition; i <= lastPosition; i++) {
                        MyAdapter.MyViewHolder holder = (MyAdapter.MyViewHolder) recyclerView.findViewHolderForAdapterPosition(i);
                        //判空
                        if (holder != null) {
                            holder.textViewNumber.setText(String.valueOf(i + 1));
                        }
                    }
                }

            }
        });//当添加数据动画结束，设置回调


        //读取用户偏好设置
        SharedPreferences sp = requireActivity().getSharedPreferences("view_type_sp", Context.MODE_PRIVATE); //字符串，访问权限
        boolean viewType = sp.getBoolean(IS_USING_CARD_VIEW, false);
        dividerItemDecoration = new DividerItemDecoration(requireActivity(),DividerItemDecoration.VERTICAL);
        if (viewType) {//用户偏好卡片则设为卡片布局
            recyclerView.setAdapter(myAdapter2);
        } else {
            recyclerView.setAdapter(myAdapter1);
            recyclerView.addItemDecoration(dividerItemDecoration);//增加下划线
        }
        filteredWords = wordViewModel.getAllWordsLive();//一开始不过滤，显示所有内容，防止切换界面之后不显示单词


        //制作添加数据时的数据信息界面反馈（添加数据自动跳转到新添加的条目位置）
        filteredWords.observe(getViewLifecycleOwner(), new Observer<List<Word>>() {
            @Override
            public void onChanged(List<Word> words) {
                int temp = myAdapter1.getItemCount();
                allWords = words;
                if (temp != words.size()) {
                    if (temp < words.size() && !undoAction) {
                        recyclerView.smoothScrollBy(0, -200);////设置滑动界面下移大于等于200个像素点，否则看不到新添加的单词
                    }
                    undoAction = false;
                    myAdapter1.submitList(words);
                    myAdapter2.submitList(words);
                }
            }
        });
        //附加recyclerView生效
        //点击悬浮按钮跳到添加单词界面
        floatingActionButton = requireActivity().findViewById(R.id.floatingActionButton);
        floatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NavController navController = Navigation.findNavController(v);
                navController.navigate(R.id.action_wordsFragment_to_addFragment);
            }
        });
    }
    @Override
    public void onResume() {
        super.onResume();
        InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
    }   //onResume()中使用，隐藏软键盘的方法。两个参数，View,第二个参数提供一些额外的操作标记，可以取0,表示什么含义没有说明，
}
